<template>
  <el-select
    v-model="name"
    v-loadmore="loadMore"
    style="width: 100%"
    :size="size"
    :loading="isFirstLoad"
    filterable
    default-first-option
    clearable
    :multiple="multiple"
    :remote="remote"
    :placeholder="placeholder"
    :remote-method="remoteMethod"
    @change="handleChange"
    @visible-change="visibleChange"
    @clear="handleClean"
    @blur="handleBlur"
  >
    <el-option
      v-for="(item, index) in options"
      :key="selectOptions.optionsKey ? item[selectOptions.optionsKey] : index"
      :label="item[selectOptions.optionsLabel]"
      :value="item[selectOptions.optionsValue]"
      :disabled="item.disabled"
    />
  </el-select>
</template>
<script>
/**
 * @param {Object} selectOptions
 * url    请求的接口
 * data   请求增加数据
 * params 请求接口的参数
 * returnStr 返回响应取值
 *
 * options 选项列表
 * optionsValue 选项 值
 * optionsLabel 选项 名称
 * optionsKey   选项 key
 */
import { $http } from '@/utils/request.js'
export default {
  props: {
    value: {
      // eslint-disable-next-line vue/require-prop-type-constructor
      type: [String, Number, Array],
      default: ''
    },
    // eslint-disable-next-line vue/require-default-prop
    label: String,
    disabled: {
      type: Array,
      default: () => []
    },
    remote: {
      type: Boolean,
      default: true
    },
    selectValue: {
      type: Boolean,
      default: false
    },
    selectOptions: {
      type: Object,
      default() {
        return {
          url: '/productShop/list',
          searchStr: 'name',
          returnStr: 'data',
          data: {},
          method: 'POST',
          optionsValue: 'id',
          optionsLabel: 'name',
          optionsKey: 'id'
        }
      }
    },
    placeholder: {
      type: String,
      default: ''
    },
    rowKey: {
      type: String,
      default: ''
    },
    // eslint-disable-next-line vue/require-default-prop
    paramsValue: Object,
    multiple: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: ''
    },
    // 是否启用筛选，部分业务中启用，eg：概览
    optionAll: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      name: '',
      searchText: '',
      timeout: null,
      options: [],
      defult_options: [],
      pageNum: 1,
      loading: false,
      isFirstLoad: true
    }
  },
  watch: {
    value(newVal, oldVal) {
      if (oldVal === '' && newVal !== '') {
        this.batchInit()
      } else if (newVal === '') {
        this.multipleValue()
      } else if (oldVal !== '' && newVal !== '') {
        this.hasVal(newVal)
      }
    }
  },
  mounted() {
    this.batchInit()
  },
  methods: {
    handleBlur() {
      this.$emit('blur')
    },
    init() {
      this.multipleValue()
    },
    clean() {
      this.name = ''
    },
    handleClean() {
      this.options = []
      this.multipleValue()
      this.pageNum = 1
      this.$emit('change', [])
      this.getCompany()
    },
    multipleValue() {
      this.name = this.multiple ? [] : ''
    },
    batchInit() {
      // 兼容使用全选不筛选的模式
      if (this.optionAll) {
        const self = this
        const promise = new Promise(function(resolve) {
          self.setValueStr(self.value, self.label, resolve)
        })
        promise.then(() => {
          this.getCompany()
        })
      } else if (!!this.value && !!this.label) {
        this.setValueStr(this.value, this.label)
      }
    },
    loadMore() {
      if (!this.selectOptions.isList) {
        this.getCompany()
      }
    },
    visibleChange() {
      if (this.options.length === 0) {
        this.pageNum = 1
        this.getCompany()
      } else {
        this.isFirstLoad = false
      }
    },
    focusCustomer() {
      var reg = this.searchText.trim()
      this.remoteMethod(reg)
    },
    getCompany() {
      if (!this.loading) {
        this.loading = true
        var parm = this.querydata()
        $http(this.selectOptions.url, parm)
          .then(r => {
            this.loading = false
            this.isFirstLoad = false
            const _data = this.$_.result(r, this.selectOptions.returnStr) || r.content
            if (_data.length > 0) {
              if (this.pageNum === 1) {
                this.options = this._result([...this.defult_options, ..._data.filter(res => res[this.selectOptions.optionsValue] !== this.value)])
              } else {
                this.options = this._result([...this.options, ..._data.filter(res => res[this.selectOptions.optionsValue] !== this.value)])
              }
              this.pageNum++
            } else {
              if (this.pageNum === 1) {
                this.options = []
              }
            }
          })
          .catch(() => {
            this.loading = false
            this.isFirstLoad = false
          })
      }
    },
    _result(ary) {
      if (this.disabled.length > 0) {
        return ary.map(r => {
          r.disabled = this.disabled.indexOf(r[this.selectOptions.optionsValue]) > -1
          return r
        })
      }
      return ary
    },
    async remoteMethod(query) {
      this.pageNum = 1
      try {
        var parm = this.querydata(query)
        var r = await $http(this.selectOptions.url, parm)
        const _data = this.$_.result(r, this.selectOptions.returnStr)
        if (_data.length > 0) {
          this.pageNum++
          this.options = this._result(_data.filter(() => r[this.selectOptions.optionsValue] !== this.value))
        } else {
          this.options = []
        }
        // eslint-disable-next-line no-empty
      } catch (error) {}
    },
    handleChange(item) {
      if (!this.selectValue) {
        var _val = ''
        if (this.rowKey) {
          if (item) {
            var _v = this.options.filter(o => o[this.selectOptions.optionsValue] === item)
            _val = _v.length > 0 ? _v[0][this.selectOptions.optionsLabel] : ''
          }
          this.$emit('change', {
            value: _val ? _v[0][this.rowKey] : '',
            label: _val
          })
          if (!this.optionAll) {
            this.$emit('changeItem', _v)
          }
        } else {
          if (Array.isArray(item)) {
            _val = this.options.filter(o => item.includes(o[this.selectOptions.optionsValue]))
          } else {
            _val = this.options.filter(o => o[this.selectOptions.optionsValue] === item)
          }
          this.$emit('change', _val)
        }

        if (this.rowKey) {
          this.$emit('input', item)
        } else {
          this.$emit('set-input', item)
        }
      } else {
        this.$emit('input', item)
      }
    },
    setValueStr(val, label, resolve) {
      if (this.name && label) {
        if (resolve) {
          resolve()
        }
        return
      }
      this.name = label
      const _o = [
        {
          [this.selectOptions.optionsLabel]: label,
          [this.selectOptions.optionsValue]: val
        }
      ]
      this.options = this._result(_o)
      this.defult_options = this._result(_o)
      if (resolve) {
        resolve()
      }
    },
    hasVal(newVal) {
      if (this.multiple) return
      const ary = this.options.filter(res => res[this.selectOptions.optionsValue] === newVal)
      var label = ary.length > 0 ? ary[0][this.selectOptions.optionsLabel] : ''
      this.name = this.label || label
      if (!this.optionAll) {
        if (ary.length === 0) {
          this.options = this._result([{ fullName: this.label, ...ary[0] }, ...this.options])
        }
      }
    },
    querydata(query) {
      let data = {}
      let str = {}

      str = {
        ...this.selectOptions.data,
        ...this.paramsValue
      }
      if (!this.selectOptions.isList) {
        str = {
          pageNum: this.pageNum,
          pageSize: 10,
          ...str
        }
      }
      if (query) {
        str = { ...str, [this.selectOptions.searchStr]: query }
      }
      if (!!this.selectOptions.method && this.selectOptions.method === 'POST') {
        data = {
          method: 'POST',
          data: str
        }
      } else {
        data = {
          method: 'GET',
          params: str
        }
      }
      return data
    }
  }
}
</script>
